package vip.xiaonuo.tasks.service;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjectUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import vip.xiaonuo.facedoor.modular.devicebase.entity.DeviceBase;
import vip.xiaonuo.facedoor.modular.devicebase.service.DeviceBaseService;
import vip.xiaonuo.facedoor.modular.memberdevice.constant.MemberDeviceConstant;
import vip.xiaonuo.facedoor.modular.memberdevice.entity.MemberDevice;
import vip.xiaonuo.facedoor.modular.memberdevice.service.MemberDeviceService;
import vip.xiaonuo.facedoor.modular.memberuser.entity.MemberUser;
import vip.xiaonuo.facedoor.modular.memberuser.service.MemberUserService;
import vip.xiaonuo.facedoor.iservice.entity.PersonBaseParam;
import vip.xiaonuo.facedoor.iservice.entity.PersonBaseParamRet;
import vip.xiaonuo.facedoor.rule.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;

@Service
@Slf4j
public class MemberIssuedService {

    @Autowired
    private MemberDeviceService memberDeviceService;

    @Autowired
    private DeviceBaseService deviceBaseService;

    @Autowired
    private MemberUserService memberUserService;

    Map<String, String> deviceType = new HashMap<String, String>() {
        {
            put("1", "人脸门禁机");
            put("7", "8寸人脸门禁机");
            put("5", "存储柜");
            put("4", "掌静脉门禁");
            put("10", "宏图设备");
        }
    };


    public void issued(Long deviceId, List<MemberDevice> memberDevices) {

        DeviceBase deviceBase = deviceBaseService.getById(deviceId);

        PersonBaseParamRet baseParam = getPersonBaseParamRet(deviceBase);

        if (memberDevices.size() > 50) {
            List<List<MemberDevice>> splitList = ListUtil.splitAvg(memberDevices, 3);
            CountDownLatch countDownLatch = new CountDownLatch(3);

            for (List<MemberDevice> memberDeviceList : splitList) {
                new Thread(() -> {
                    try {
                        issued(memberDeviceList, baseParam, deviceBase);
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        countDownLatch.countDown();
                    }
                }).start();
            }
            try {
                countDownLatch.await();
            } catch (InterruptedException e) {
                log.error("当前线程已经被中断！");
            }
        } else {
            issued(memberDevices, baseParam, deviceBase);
        }
    }


    private void issued(List<MemberDevice> memberDevices, PersonBaseParamRet baseParam, DeviceBase deviceBase) {
        // 基础检查
        if (!deviceType.containsKey(deviceBase.getDeviceType())) {
            return;
        }
        for (MemberDevice memberDevice : memberDevices) {
            MemberUser memberUser = memberUserService.getById(memberDevice.getMemberId());
            if (memberUser == null) {
                memberDeviceService.removeById(memberDevice.getId());
                continue;
            }
            // 先查询人员
            switch (memberDevice.getStatus()) {
                case MemberDeviceConstant.ADD:
                    if (check(deviceBase, memberDevice, MemberDeviceConstant.ADD_FAIL)) {
                        continue;
                    }
                    log.info("开始下发人员【{}】【{}】", memberUser.getName(), memberUser.getJobNum());
                    addPerson(memberDevice, memberUser, baseParam);
                    break;
                case MemberDeviceConstant.DELETE:
                    if (check(deviceBase, memberDevice, MemberDeviceConstant.DELETE_FAIL)) {
                        continue;
                    }
                    log.info("开始删除人员【{}】【{}】", memberUser.getName(), memberUser.getJobNum());

                    deletePerson(memberDevice, memberUser, baseParam);
                    break;
                case MemberDeviceConstant.UPDATE:
                    if (check(deviceBase, memberDevice, MemberDeviceConstant.UPDATE_FAIL)) {
                        continue;
                    }
                    log.info("开始修改人员【{}】【{}】", memberUser.getName(), memberUser.getJobNum());
                    updatePerson(memberDevice, memberUser, baseParam);
                    break;
            }
        }
    }

    private boolean check(DeviceBase deviceBase, MemberDevice memberDevice, int updateFail) {
        if (StringUtils.isBlank(deviceBase.getDeviceState()) || deviceBase.getDeviceState().equals("2")) {
            log.error("设备【{}】已经断线 无法进行人员下发", deviceBase.getName());
            memberDevice.setFailReason("设备已经断线 无法进行人员下发");
            memberDevice.setStatus(updateFail);
            memberDeviceService.updateById(memberDevice);
            return true;
        }
        return false;
    }


    private static PersonBaseParamRet getPersonBaseParamRet(DeviceBase deviceBase) {
        return DeviceTypeRuleService.getIMemberDealWithService(deviceBase.getDeviceType()).getBaseParam(new PersonBaseParam().setDeviceBase(deviceBase));
    }

    private void updatePerson(MemberDevice memberDevice, MemberUser memberUser, PersonBaseParamRet baseParam) {
        DeviceBase deviceBase = deviceBaseService.getById(memberDevice.getDeviceId());
        try {
            DeviceTypeRuleService.getIMemberDealWithService(deviceBase.getDeviceType()).update(memberDevice, memberUser, baseParam, deviceBase);
        } catch (Exception e) {
            DeviceTypeRuleService.getIMemberDealWithService(deviceBase.getDeviceType()).updateException(memberDevice, memberUser, deviceBase, e);
        }
    }


    private void deletePerson(MemberDevice memberDevice, MemberUser memberUser, PersonBaseParamRet personBaseParamRet) {
        DeviceBase deviceBase = deviceBaseService.getById(memberDevice.getDeviceId());
        try {
            DeviceTypeRuleService.getIMemberDealWithService(deviceBase.getDeviceType()).delete(memberDevice, memberUser, personBaseParamRet, deviceBase);
        } catch (Exception e) {
            DeviceTypeRuleService.getIMemberDealWithService(deviceBase.getDeviceType()).deleteException(memberDevice, memberUser, deviceBase, e);
        }
    }

    private void addPerson(MemberDevice memberDevice, MemberUser memberUser, PersonBaseParamRet baseParam) {
        DeviceBase deviceBase = deviceBaseService.getById(memberDevice.getDeviceId());
        try {
            DeviceTypeRuleService.getIMemberDealWithService(deviceBase.getDeviceType()).add(memberDevice, memberUser, baseParam, deviceBase);
        } catch (Exception e) {
            DeviceTypeRuleService.getIMemberDealWithService(deviceBase.getDeviceType()).addException(memberDevice, memberUser, deviceBase, e);
        }
    }
}
